package com.matt.sooncleaner.junk

import android.R.attr
import android.content.Context
import android.os.Bundle
import android.util.Log
import com.cleanmaster.junk.bean.SDcardRubbishResult
import com.cloud.cleanjunksdk.ad.AdvBean
import com.cloud.cleanjunksdk.cache.CacheBean
import com.cloud.cleanjunksdk.filescan.ApkBean
import com.cloud.cleanjunksdk.filescan.LogBean
import com.cloud.cleanjunksdk.filescan.TmpBean
import com.cloud.cleanjunksdk.residual.ResidualBean
import com.cloud.cleanjunksdk.task.Clean
import com.cloud.cleanjunksdk.task.JunkScanCallback
import com.cm.plugincluster.junkengine.junk.bean.MediaFile
import com.cm.plugincluster.junkengine.junk.engine.MEDIA_TYPE
import com.matt.sooncleaner.R
import com.matt.sooncleaner.arch.ArchFragment
import com.matt.sooncleaner.databinding.FragmentJunkScanBinding
import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.File
import java.util.concurrent.TimeUnit


const val JUNK_SCAN_TAG = "JunkScanFragment"

class JunkScanFragment : ArchFragment<FragmentJunkScanBinding>() {

    interface OnJunScanListener {
        fun onScanFinish(junkScanResult: MutableList<JunkBean>)
    }

    private val junkBeans = mutableListOf<JunkBean>()

    private var cleanSdk: Clean? = null
    private val adBeans = ArrayList<JunkChildBean>()
    private val apkBeans = ArrayList<JunkChildBean>()
    private val tmpBeans = ArrayList<JunkChildBean>()
    private val logBeans = ArrayList<JunkChildBean>()
    private val appCacheBeans = ArrayList<JunkChildBean>()
    private val residualBeans = ArrayList<JunkChildBean>()
    private val systemBeans = ArrayList<JunkChildBean>()

    //private ArrayList<JunkChildBean> bigfileBeans = new ArrayList<>();
    private val phohoBeans = ArrayList<JunkChildBean>()
    private val videoBeans = ArrayList<JunkChildBean>()
    private val audioBeans = ArrayList<JunkChildBean>()
    private val thumbnailBeans = ArrayList<JunkChildBean>()
    private val docBeans = ArrayList<JunkChildBean>()

    private val adJunkMotherBean: JunkBean = JunkBean()
    private val apkJunkMotherBean: JunkBean = JunkBean()
    private val tmpJunkMotherBean: JunkBean = JunkBean()
    private val logJunkMotherBean: JunkBean = JunkBean()
    private val appCacheJunkMotherBean: JunkBean = JunkBean()
    private val residualJunkMotherBean: JunkBean = JunkBean()
    private val systemJunkMotherBean: JunkBean = JunkBean()

    private val phohoJunkMotherBean: JunkBean = JunkBean()
    private val videoJunkMotherBean: JunkBean = JunkBean()
    private val audioJunkMotherBean: JunkBean = JunkBean()
    private val thumbnailJunkMotherBean: JunkBean = JunkBean()
    private val docJunkMotherBean: JunkBean = JunkBean()


    private var systemFinish = false
    private var adFinish = false
    private var apkFinish = false
    private var tmpFinish = false
    private var logFinish = false
    private var appCacheFinish = false
    private var residualFinish = false

    //private boolean bigFileFinish;
    private var videoFinish = false
    private var photoFinish = false
    private var audioFinish = false
    private var thumbnailFinish = false
    private var docFinish = false
    private var screenshotFinish = false

    private var mDispose: Disposable? = null
    private var mOnJunScanListener: OnJunScanListener? = null
    private var ipakageStatatsTools: IpakageStatatsTools? = null

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is OnJunScanListener) {
            mOnJunScanListener = context
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        mScanStepList.add(AdJunkScanStep())
//        mScanStepList.add(ApkJunkScanStep())
//        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
//            mScanStepList.add(AppCacheJunkScanStep())
//        }
//        mScanStepList.add(DocJunkScanStep())
//        mScanStepList.add(ResidualJunkScanStep())
//        mScanStepList.add(mSystemCacheJunkScanStep)
//        mScanStepList.add(TmpJunkScanStep())
//        mScanStepList.add(LogJunkScanStep())
//        mScanStepList.add(VideoJunkScanStep())
//        mScanStepList.add(PhotoJunkScanStep())
//        mScanStepList.add(AudioJunkScanStep())
        ipakageStatatsTools = IpakageStatatsTools()
        initData()
    }

    private fun initData() {
        junkBeans.clear()
        adJunkMotherBean.junkChildrenItem = adBeans
        apkJunkMotherBean.junkChildrenItem = apkBeans
        tmpJunkMotherBean.junkChildrenItem = tmpBeans
        logJunkMotherBean.junkChildrenItem = logBeans
        appCacheJunkMotherBean.junkChildrenItem = appCacheBeans
        residualJunkMotherBean.junkChildrenItem = residualBeans
        systemJunkMotherBean.junkChildrenItem = systemBeans

        //bigfileJunkMotherBean.setJunkChildrenItem(bigfileBeans);
        videoJunkMotherBean.junkChildrenItem = videoBeans
        phohoJunkMotherBean.junkChildrenItem = phohoBeans
        audioJunkMotherBean.junkChildrenItem = audioBeans
        thumbnailJunkMotherBean.junkChildrenItem = thumbnailBeans
        docJunkMotherBean.junkChildrenItem = docBeans

        adJunkMotherBean.name = getString(R.string.ad_junk)
        apkJunkMotherBean.name = getString(R.string.apk_junk)
        tmpJunkMotherBean.name = getString(R.string.tmp_junk)
        logJunkMotherBean.name = getString(R.string.log_junk)
        appCacheJunkMotherBean.name = getString(R.string.app_cache_junk)
        residualJunkMotherBean.name = getString(R.string.residual_junk)
        systemJunkMotherBean.name = getString(R.string.system_cache)
        //bigfileJunkMotherBean.setName(context.getResources().getString(R.string.big_file_title));
        videoJunkMotherBean.name = getString(R.string.video)
        phohoJunkMotherBean.name = getString(R.string.photo)
        audioJunkMotherBean.name = getString(R.string.audio)
        thumbnailJunkMotherBean.name = getString(R.string.thumbnail)
        docJunkMotherBean.name = getString(R.string.doc)

        adJunkMotherBean.size = 0
        apkJunkMotherBean.size = 0
        tmpJunkMotherBean.size = 0
        logJunkMotherBean.size = 0
        appCacheJunkMotherBean.size = 0
        residualJunkMotherBean.size = 0
        systemJunkMotherBean.size = 0

        //bigfileJunkMotherBean.setSize(0);
        videoJunkMotherBean.size = 0
        phohoJunkMotherBean.size = 0
        audioJunkMotherBean.size = 0
        thumbnailJunkMotherBean.size = 0
        docJunkMotherBean.size = 0


        junkBeans.add(adJunkMotherBean)
        junkBeans.add(apkJunkMotherBean)
        junkBeans.add(appCacheJunkMotherBean)
        junkBeans.add(docJunkMotherBean)
        junkBeans.add(residualJunkMotherBean)
        junkBeans.add(systemJunkMotherBean)
        junkBeans.add(tmpJunkMotherBean)
        junkBeans.add(logJunkMotherBean)

        //junkBeans.add(bigfileJunkMotherBean);
        junkBeans.add(videoJunkMotherBean)
        junkBeans.add(phohoJunkMotherBean)
        junkBeans.add(audioJunkMotherBean)
        junkBeans.add(thumbnailJunkMotherBean)
    }

    private val mJunkScanCallback = object : JunkScanCallback {
        override fun onStart() {
        }

        override fun error(errorCode: Int, throwable: Throwable?) {
        }

        override fun onAdJunkEmitOne(advBean: AdvBean?) {
            advBean ?: return
            val path = advBean.path // file path
            val size = advBean.size // file size in bytes
            val name = advBean.name // file name
            Log.d(JUNK_SCAN_TAG, "onAdJunkEmitOne: path" + path + "size" + size + "name" + name)
            val junkChildBean = JunkChildBean()
            junkChildBean.path = path
            junkChildBean.size = size
            junkChildBean.name = name
            adBeans.add(junkChildBean)
            val nowSize = adJunkMotherBean.size + size
            adJunkMotherBean.size = nowSize
        }

        override fun onAdJunkSucceed() {
            adFinish = true;
            checkAllFinish()
        }

        override fun onApkJunkEmitOne(apkBean: ApkBean?) {
            apkBean ?: return
            val name: String = apkBean.name // file name
            val path: String = apkBean.path // file path
            val size: Long = apkBean.size // file size in bytes
            Log.d(JUNK_SCAN_TAG, "onApkJunkEmitOne: " + apkBean.toString())
            val junkChildBean = JunkChildBean()
            junkChildBean.path = path
            junkChildBean.size = size
            junkChildBean.name = name
            apkBeans.add(junkChildBean)
            val nowSize = apkJunkMotherBean.size + size
            apkJunkMotherBean.size = nowSize
        }

        override fun onApkJunkScanSucceed() {
            apkFinish = true
            checkAllFinish()
        }

        override fun onTmpJunkEmitOne(tmpBean: TmpBean?) {
            tmpBean?:return
            val name: String = tmpBean.getName() // file name
            val path: String = tmpBean.getPath() // file path
            val size: Long = tmpBean.getSize() // file size in bytes
            Log.d(JUNK_SCAN_TAG, "onTmpJunkEmitOne: " + tmpBean.toString())
            val junkChildBean = JunkChildBean()
            junkChildBean.path = path
            junkChildBean.size = size
            junkChildBean.name = name
            tmpBeans.add(junkChildBean)
            val nowSize = tmpJunkMotherBean.size + size
            tmpJunkMotherBean.size = nowSize
        }

        override fun onTmpJunkScanSucceed() {
            tmpFinish = true
            checkAllFinish()
        }

        override fun onLogJunkEmitOne(logBean: LogBean?) {
            logBean ?: return
            val name: String = logBean.getName() // file name
            val path: String = logBean.getPath() // file path
            val size: Long = logBean.getSize() // file size in bytes
            Log.d(JUNK_SCAN_TAG, "onLogJunkEmitOne: " + logBean.toString())
            val junkChildBean = JunkChildBean()
            junkChildBean.path = path
            junkChildBean.size = size
            junkChildBean.name = name
            logBeans.add(junkChildBean)
            val nowSize = logJunkMotherBean.size + size
            logJunkMotherBean.size = nowSize
        }

        override fun onLogJunkScanSucceed() {
            logFinish = true
            checkAllFinish()
        }

        override fun onCacheJunkEmitOne(cacheBean: CacheBean) {
            Log.i(JUNK_SCAN_TAG, "appCache scan: ${cacheBean?.size}")
            val packageName: String = cacheBean.packageName // package name
            val name: String = cacheBean.appName // app name
            val size: Long = cacheBean.size // cache junk size
            val junkChildBean = JunkChildBean()
            junkChildBean.size = size
            junkChildBean.name = name
            junkChildBean.isAppCache = true
            val nowSize = appCacheJunkMotherBean.size + size
            appCacheJunkMotherBean.size = nowSize
            for (pathBean in cacheBean.getPathBeen()) { // there can be many cache junk files for one app
                Log.d(JUNK_SCAN_TAG, ("cacheBeanArrayList:" + pathBean.toString()).toString() + "")
                val desc_name: String = pathBean.getCacheJunkDesc() // cache description
                val path: String = pathBean.getCleanPath() // cache path
                val sizeP: Long = pathBean.getSize() // cache size
                val appCacheBean = AppCacheBean()
                appCacheBean.name = desc_name
                appCacheBean.path = path
                appCacheBean.isDeep = pathBean.isDeep()
                appCacheBean.size = sizeP
                junkChildBean.appCacheBeens.add(appCacheBean)
            }
            appCacheBeans.add(junkChildBean)
        }

        override fun onCacheJunkSucceed() {
            appCacheFinish = true;
            checkAllFinish();
        }

        override fun onResidualEmitOne(residualBean: ResidualBean) {
            Log.i(JUNK_SCAN_TAG, "onResidualEmitOne: ${residualBean.size}")
            val path: String = residualBean.path // residual path
            val name: String = residualBean.desc // residual app name
            val size: Long = residualBean.size // residual size
            Log.d(JUNK_SCAN_TAG, "onResidualJunkSucceed: " + residualBean.toString())
            val junkChildBean = JunkChildBean()
            junkChildBean.path = path
            junkChildBean.size = size
            junkChildBean.name = name
            val nowSize = residualJunkMotherBean.size + size
            residualJunkMotherBean.size = nowSize
            residualBeans.add(junkChildBean)
        }

        override fun onResidualJunkSucceed() {
            residualFinish = true
            checkAllFinish()
        }

        override fun onTimeOut() {
            Log.i(JUNK_SCAN_TAG, "onTimeOut")
//            finishScanStep()
        }

        override fun onThumbnailJunkEmitOne(sDcardRubbishResult: SDcardRubbishResult) {
            val paths = sDcardRubbishResult.pathList
            for (path in paths) {
                val name = sDcardRubbishResult.name
                val size = sDcardRubbishResult.size
                Log.d(JUNK_SCAN_TAG, "onResidualJunkSucceed: " + sDcardRubbishResult.strDirPath)
                val junkChildBean = JunkChildBean()
                junkChildBean.path = path
                junkChildBean.size = File(path).length()
                junkChildBean.name = name
                val nowSize = thumbnailJunkMotherBean.size + size
                thumbnailJunkMotherBean.size = nowSize
                thumbnailBeans.add(junkChildBean)
            }
        }

        override fun onThumbnailJunkScanSucceed() {
            thumbnailFinish = true;
            checkAllFinish();
        }

        override fun onMediaFileJunkEmitOne(type: MEDIA_TYPE, mediaFile: MediaFile) {
            Log.i(JUNK_SCAN_TAG, "onMediaFileJunkEmitOne size: ${mediaFile.size}")
            val path = mediaFile.getPath()
            val title = mediaFile.getTitle()
            val size = mediaFile.size
            Log.d(JUNK_SCAN_TAG, "onMediaEmitOne: $mediaFile".toString() + "，type：" + attr.type)
            val junkChildBean = JunkChildBean()
            junkChildBean.path = path
            junkChildBean.size = size
            junkChildBean.name = title
            if (type.ordinal == MEDIA_TYPE.PHOTO.ordinal) {
                val nowSize = phohoJunkMotherBean.size + size
                Log.d(
                    JUNK_SCAN_TAG,
                    "onMediaEmitOne nowSize: $nowSize,size:$size"
                )
                phohoJunkMotherBean.size = nowSize
                phohoBeans.add(junkChildBean)
            } else if (type.ordinal == MEDIA_TYPE.VIDEO.ordinal) {
                val nowSize = videoJunkMotherBean.size + size
                videoJunkMotherBean.size = nowSize
                videoBeans.add(junkChildBean)
            } else if (type.ordinal == MEDIA_TYPE.AUDIO.ordinal) {
                val nowSize = audioJunkMotherBean.size + size
                audioJunkMotherBean.size = nowSize
                audioBeans.add(junkChildBean)
            } else if (type.ordinal == MEDIA_TYPE.DOC.ordinal) {
                val nowSize = docJunkMotherBean.size + size
                docJunkMotherBean.size = nowSize
                docBeans.add(junkChildBean)
            }
        }

        override fun onMediaFileJunkScanSucceed(type: MEDIA_TYPE) {
            Log.i(JUNK_SCAN_TAG, "onMediaFileJunkScanSucceed, type: ${type.name}")
            if (type.ordinal == MEDIA_TYPE.PHOTO.ordinal) {
                photoFinish = true;
            } else if (type.ordinal == MEDIA_TYPE.VIDEO.ordinal) {
                videoFinish = true;
            } else if (type.ordinal == MEDIA_TYPE.AUDIO.ordinal) {
                audioFinish = true;
            } else if (type.ordinal == MEDIA_TYPE.DOC.ordinal) {
                docFinish = true;
            } else if (type.ordinal == MEDIA_TYPE.SCREENSHOT.ordinal) {
                screenshotFinish = true;
            }
            checkAllFinish();
        }
    }

    override fun onInitView(binding: FragmentJunkScanBinding) {
        super.onInitView(binding)
        binding.progressView.setProgressAnimationDuration(5000L)

        cleanSdk = CleanManager.getCleanSdk()
        binding.progressView.setMax(100f)
        binding.progressView.setProgressAnimationDuration(20000)
        binding.progressView.setProgress(100f, true)
        binding.progressView.setProgressEndListener {
            mOnJunScanListener?.onScanFinish(junkBeans)
        }
        startScan()
    }

    private var mIsAllFinish = false

    private fun checkAllFinish() {
        if (adFinish &&
            apkFinish &&
            tmpFinish &&
            logFinish &&
            appCacheFinish &&
            residualFinish &&
            systemFinish &&  //bigFileFinish &&
            videoFinish &&
            photoFinish &&
            audioFinish &&
            thumbnailFinish &&
            docFinish &&
            screenshotFinish
        ) {
            binding?.progressView?.setProgress(100f)
        }
    }

    private fun startScan() {
        ipakageStatatsTools = IpakageStatatsTools()
        ipakageStatatsTools!!.startObserver(systemBeans, systemJunkMotherBean)

        mDispose = Flowable.interval(100, TimeUnit.MILLISECONDS)
            .onBackpressureLatest()
            .subscribeOn(Schedulers.newThread())
            .takeUntil {
                if (!ipakageStatatsTools!!.runObserver) {
                    systemFinish = true
                }
                !ipakageStatatsTools!!.runObserver
            }
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                checkAllFinish()
            }
        cleanSdk?.startScan(mJunkScanCallback, true)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        mDispose?.dispose()
        cleanSdk?.cancel()
    }
}